package com.zj.musicTools.page

import android.annotation.SuppressLint
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Snackbar
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import com.zj.musicTools.MainActivity.Companion.Agent
import com.zj.musicTools.R
import com.zj.musicTools.function.AppPath.Companion.appPath
import com.zj.musicTools.function.Decrypt
import com.zj.musicTools.function.FFMPEG
import com.zj.musicTools.function.perhandler
import com.zj.musicTools.page.buttonText.normal
import com.zj.musicTools.page.buttonText.run
import com.zj.musicTools.ui.theme.MusicToolsTheme
import com.zj.musicTools.ui.theme.black
import com.zj.musicTools.ui.theme.musicGreen3
import com.zj.musicTools.ui.theme.musicRed
import org.json.JSONObject
import java.io.File
import java.util.regex.Matcher
import java.util.regex.Pattern


//var ff = 1.sp
//运行按钮状态
enum class buttonText(
    val text:String,
    val size:TextUnit,
    val clickable:Boolean
){
    normal("运行",26.sp,true),
    run("运行中",17.sp,false)
}


//var buttonName by mutableStateOf("开始")
var runResult by mutableStateOf("")//运行结果  0:未运行 1：成功  2：出错
var buttonState by mutableStateOf(normal)
private var runMode by mutableStateOf(7) //用二进制表示： 111  第1位，是否全自动，第2位，是否解密 第3位：是否转码，第4位，是否剪辑
private val listFile: MutableList<String> = mutableListOf("")
private val listDecrypt: MutableList<String> = mutableListOf("")
private var fileType:String = "flac"
private var errResult:Int = 0

/**
 * 用于切换第index位的工作状态(从0 开始)
 *  //待测试后使用
* */
fun modeSwitch(index:Int,value:Boolean){
    Log.i("modeSwitch()","set ${index+1} to $value")
    val bitmask = 0x1 shl index
    runMode = if(value) bitmask or runMode else bitmask.inv() and runMode
    //runMode =  bitmask xor runMode //把第index位取反
}
/**
 * 获取模式index位的状态
* */
fun modeGet(index:Int):Boolean{
    return (runMode ushr index) and 0x01 == 1
}

fun decrypt(name: String,outname: String=""){

    if(!modeGet(1))return
    listDecrypt.clear()

    Decrypt(inFile = name, callback ={//callback内容
            result ->
        if (result.isSuccess) {
            Log.i("decrypt()", result.getOrNull().toString())
            runResult = "解密成功"
//            listDecrypt.add(outname)
            getList(result.getOrNull().toString())

//            lister.getList()
        }else {
            Log.e("decrypt()", result.getOrNull().toString())
            runResult = "解密失败"
        }
        if(!(modeGet(2) || modeGet(3))) {//如果处于只解密模式，则结束
            Log.i("decrypt()","only decrypt")
            buttonState = normal
        }
        else
            ffmpeg(name,outname)

        modeSwitch(1,false) //结束解密

    })

}

/**
 * 处理输入文件列表，转化成单个文件
 * */
fun ffmpeg(input:String, output:String){
    /*文件模式才使用output，目录模式使用原文件名重命名*/

//    val putName = if(listFile[0] == "single") listFile[1] else null//单文件模式
    //目录模式，从目录中获取输入文件
    if(!(modeGet(2) || modeGet(3))) {
        buttonState=normal
        return
    }

    Log.i("ffmpeg()"," output:${output}")
    //初始化输入文件列表
    var outname:String?=null
    val dirlist=File(input)
    if(dirlist.isDirectory){ //目录模式
        listFile.clear()//清空列表
        traverseFileTreeOneLevel(dirlist){
            Log.i("inPath:", it)
            listFile.add(it)
        }
    }else{
        Log.i("ffmpeg()"," listDecrypt.size:${listDecrypt.size}")

        listFile.clear()//清空列表
        listFile.add(if(listDecrypt.size > 0) listDecrypt[0] else input)
        Log.i("inPath:", listFile[0] +"  list:"+listFile)
        outname=output
//        FFMPEG.init(input, output.suffix(fileType))
    }


//执行ffmpeg命令
    errResult=0
    val exec=Agent.executorService
    exec.submit {//线程执行
        for (i in listFile) {
            if (!inputFiltering(i)) {//遇到不支持的文件格式直接跳过
//                if (i == listFile[listFile.size]) buttonState = normal
                continue
            }
            Log.i("putPath:", i)
            outname = outname ?: i.suffix(fileType)

            if (modeGet(3) || i != outname) {//格式不一致才需要转码，目的是为了避免开启了自动转码但是格式一致的情况消耗资源
                Log.i("FFMPEG init", i)

                val rebuildFile = File(outname!!)
                if (rebuildFile.exists() && rebuildFile.isFile) rebuildFile.delete()//删除已存在的文件

                FFMPEG.init(input = i, output = outname, callback = {
                    if (it != 0) errResult++
                    else {
                        for (rm in listDecrypt) {//匹配并删除已成功转码的解密文件
                            Log.i("ffmpeg() exec","delete file:${rm}")
                            if (rm == i && File(outname).exists() ) File(rm).delete()
                        }
                    }

                })
                runResult = "${i.getName()} -> ${outname!!.getName()}"
                FFMPEG.run()
            }
            outname=null
        }
        runResult = if (errResult == 0)                    "转码成功"
                    else if (errResult == listFile.size)   "转码失败"
                    else                                   "部分失败"

        buttonState = normal
        modeSwitch(2,false)
        modeSwitch(3,false)
    }

}

// lateinit var decrypter:Decrypt //log函数不要写在decrypter类里面，与其无关

private fun buttonRun(name: String,outname:String) {
    //提供输入和输出路径，然后合并为命令，还需要补充其他的命令参数，如时间、格式 等信息，//应该将ffmpeg（）移到本页面，用于处理选择项，判断运行模式，再使用FFMPEG类执行相对应的命令。以后有更多的ffmpeg功能也可以直接在ffmpeg()里面处理转化为对应的调用
//    Log.w("!!!!!!!!!!", "text:" + readTextFromFile("/storage/self/primary/netease/cloudmusic/Music/NewTextFile.txt"))


        Log.i("debug", "musicName:$name")
//        val decrypter= Decrypt(name,autoRun=false)
        buttonState = run
        runResult = ""
        decrypt(name, outname)

//        val catchData=decrypter.run()
//        Log.i("!!!!!!!!!!", "tryDecFile():"+catchData)
//        if(!modeGet(1))ffmpeg(name,outname)//解密的时候是不是会进入呢？
}


/*
 * Android 10 以上适配 另一种写法
 * @param context
 * @param uri
 * @return
 */
/*
@SuppressLint("Range")
fun contentPath(context: Context, uri: Uri?): String? {
    if (uri == null) {
        return null
    }
    val filePath: String
    val filePathColumn =
        arrayOf(MediaStore.DownloadColumns.DATA, MediaStore.DownloadColumns.DISPLAY_NAME)
    val contentResolver = context.contentResolver
    val cursor = contentResolver.query(
        uri, filePathColumn, null,
        null, null
    )
    if (cursor != null) {
        cursor.moveToFirst()
        try {
            filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]))
            return filePath
        } catch (e: Exception) {
        } finally {
            cursor.close()
        }
    }
    return ""
}*/

/**
 * 从获取返回的log中获取成功的文件列表
* */
fun getList(logBuf:String){
    val logdata=logBuf.get("data").toString()
//    Log.i("getList()",logdata)
    val succeed= logdata.split("失败信息")[0]//获取成功信息
//    Log.i("getList()",succeed)
    if(succeed.contains("解码成功",ignoreCase=true)) {
        listDecrypt.clear()//清空列表
//        Log.i("getList()",succeed)
        for (path in succeed.split("解码成功")) {
//            Log.i("getList()",path)
            if(path.contains("输出文件",ignoreCase=true)) {
                val pos = path.indexOf("输出文件")
                val pos1 = path.indexOf("]")
                listDecrypt.add(path.substring(pos + "输出文件[".length, pos1))
            }
        }
    }


}
/**
 * 获取json数据值
 * */
fun String.get(key: String): Any? {
    return try {
        val jsonMessage = this
        val jsonObject = JSONObject(jsonMessage)
        jsonObject.get(key)
    } catch (e: Exception) {
        null
    }
}

/**
 * 输入格式过滤，为避免后续不必要的麻烦
 *
 *     aac（Advanced Audio Coding，高级音频编码）
 *     ac3（Dolby Digital，杜比数字）
 *     acm（Audio Codec Manager，音频编解码管理器）
 *     aiff（Audio Interchange File Format，音频交换文件格式）
 *     alaw（A Law，A律压缩）
 *     amr（Adaptive Multi-Rate，自适应多速率）
 *     ape（Monkey's Audio，猴子音频）
 *     au（Sun Microsystems AU audio file format，太阳微系统AU音频文件格式）
 *     flac（Free Lossless Audio Codec，自由无损音频编解码器）
 *     m4a（MPEG-4 Part 14，MPEG-4第14部分）
 *     mp3（Moving Picture Experts Group Audio Layer III，动态图像专家组音频层III）
 *     oga（Ogg Vorbis，Ogg Vorbis）
 *     ogg（Ogg Container，Ogg容器）
 *     pcm（Pulse Code Modulation，脉冲编码调制）
 *     wav（Waveform Audio File Format，波形音频文件格式）
 *   @return
 *   true:格式支持
 *   false：不支持
 *
 * */

fun inputFiltering(input:String):Boolean{
    val formatList = arrayOf(".aac", ".ac3",".acm",".aiff",".alaw",".amr",".ape",".au",".flac",".m4a",".mp3",".oga",".ogg",".pcm",".wav")
    Log.i("inputFiltering()","inputfile:${input}")
    for (value in formatList){
        val inFormat=input.getSuffix()
        Log.i("inputFiltering()","get format:${inFormat}")
        if(inFormat.contains(value,ignoreCase=true))
            return true
    }
    return false
}

/**
 * 检测是否需要修改文件名
* */
fun nameCheck(filepath:String):String{
//    { ".ncm",      (Vendors.NetEase,    AudioTypes.Undefined) },
//    { ".kgm",      (Vendors.Kugou,      AudioTypes.Undefined) },
//    { ".kgma",     (Vendors.Kugou,      AudioTypes.Undefined) },
//    { ".vpr",      (Vendors.Kugou,      AudioTypes.Undefined) },
//    { ".kwm",      (Vendors.Kuwo,       AudioTypes.Undefined) },
//    { ".xm",       (Vendors.Xiami,      AudioTypes.Undefined) },
//    { ".x2m",      (Vendors.Ximalaya,   AudioTypes.Undefined) },
//    { ".x3m",      (Vendors.Ximalaya,   AudioTypes.Undefined) },
    val keywords = arrayOf(".ncm", ".kgm",".kgma",".vpr",".kwm",".xm",".x2m",".x3m")
    var buf=""

    for (index in keywords){
        if(filepath.contains(index,ignoreCase=true)) {
            val pos = filepath.indexOf(index)
            if(pos+index.length == filepath.length) {
                Log.i("nameCheck()","name pass")
                continue
            }else {
                buf = filepath.substring(0, pos + index.length)
                Log.i("nameCheck()", "name [$filepath] need change to $buf")
            }
        }
    }
    if(buf.isEmpty())buf=filepath

    return buf
}
/**
* 遍历目录子项，若子项非目录文件则 回调该文件路径同时执行task(String)
* */
private fun traverseFileTreeOneLevel(file: File,task:((String) -> Unit)?) {
    file.listFiles()?.let { children ->
        children.forEach { child ->
            if (!child.isDirectory) {
                task?.let { it(child.absolutePath) }
//                rename(child.absolutePath)
            }
        }
    }
}
/**
* rename 重命名文件名，用于应对新版本酷狗音乐修改后缀的问题
* */
fun rename(filepath:String):String{
    val file = File(filepath)
//    MainActivity.Agent.log("original path: "+filepath)
    if(file.isDirectory()){
        traverseFileTreeOneLevel(file) {
            rename(it)
        }
    }else {
        val newfilePath = nameCheck(filepath)
        if (newfilePath != filepath) {
            Log.i("rename()", "rename to [$newfilePath]")
            val rt = file.renameTo(File(newfilePath))
            Agent.log(if(rt) "rename to [$newfilePath]" else "rename [$newfilePath] failed.")

            Log.i("rename()", "change:$rt")
            return newfilePath
        }

    }
    return filepath
}
/**
 * 修改文件路径
 * *设置常用路径时会用到
 * */
fun String.reDir(path:String):String{
    val filename = this.substring(this.lastIndexOf('/')+1,this.length) //获取最后一个 / 后面的文件名

    return path+filename
}

/**
 * 获取文件名
 * */
fun String.getName():String{
    return this.substring(this.lastIndexOf('/')+1,this.length) //获取最后一个 / 后面的文件名
}

/**
 * suffix 修改后缀
 * */
fun String.suffix(value:String):String{
    val filepath = this
    val buf:String
    val file = filepath.substring(filepath.lastIndexOf('/')+1,filepath.length) //获取最后一个 / 后面的文件名
    //    MainActivity.Agent.log("original path: "+filepath)
    //确保最后一个 / 后面存在正确的文件名
    if(file.contains('.')) {
        val pos = filepath.lastIndexOf('.' )
        buf = filepath.substring(0, pos+1)+value
        Log.i("suffix()", "name [$filepath] need change to $buf")
        return buf
    }
    return filepath
}

/**
 * suffix 获取后缀
 * */
fun String.getSuffix():String{
    val filepath = this
    val buf:String
    val file = filepath.substring(filepath.lastIndexOf('/')+1,filepath.length) //获取最后一个 / 后面的文件名
    //    MainActivity.Agent.log("original path: "+filepath)
    //确保最后一个 / 后面存在正确的文件名
    if(file.contains('.')) {
        val pos = filepath.lastIndexOf('.')
        buf = filepath.substring(pos, filepath.length)
//        Log.i("getSuffix()", "name [$filepath] getFormat: $buf")
        return buf
    }
    return ""
}

/**
 *  验证时间格式的函数
 *
 *  */
fun String.isValidTime(): Boolean {
    // 使用正则表达式验证时间格式
    val timePattern = "^([0-9][0-9]):([0-5][0-9]):([0-5][0-9]).([0-9][0-9][0-9])$"
    val pattern: Pattern = Pattern.compile(timePattern)
    val matcher: Matcher = pattern.matcher(this)
    return matcher.matches()
}
/**
 * 纠正时间格式
 * */
fun String.formatTimeString(): String {
    Log.i(".formatTimeString","start")

    // 假设输入的时间格式为 "HH:mm:ss.SSS" 或 "H:mm:ss"
    val pattern =  """(\d+):(\d+):(\d+).(\d+)""".toRegex()
    Log.i(".formatTimeString","pattern")

    val putbuf= pattern.replace(this) { matchResult ->
        val (hours, minutes, seconds,millionsec) = matchResult.destructured
        // 去除小时、分钟和秒数的前导0
        Log.i(".formatTimeString","min:${minutes.toInt()},sec:${seconds.toInt()},millionsec:${millionsec.toInt()}")
        val formattedHours =  (if(hours.toInt()>99)0 else hours.toInt()).toString().padStart(2, '0')
        val formattedMinutes =(if(minutes.toInt()>59)0 else minutes.toInt()).toString().padStart(2, '0')
        val formattedSeconds =(if(seconds.toInt()>59)0 else seconds.toInt()).toString().padStart(2, '0')
        val formattedMillionSec = (if(millionsec.toInt()>999)0 else millionsec.toInt()).toString().padStart(3, '0')

        "$formattedHours:$formattedMinutes:$formattedSeconds.$formattedMillionSec"
    }
    return if(putbuf.isValidTime()) putbuf else "00:00:00.000${Agent.ToastLog("时间格式错误")}"

}

@OptIn(ExperimentalComposeUiApi::class)
@SuppressLint("SuspiciousIndentation")
@Composable
fun MainPage() {
    var textdata by remember {
        mutableStateOf("/sdcard/Download/netease/cloudmusic/Music/")
    }
    val UriData = remember {
        mutableStateOf("".toUri())
    }//URI路径，暂时无用
    var pathType by remember { mutableStateOf(true) }/*地址类型，true为文件夹，false为单文件*/
    var copyCut by remember { mutableStateOf(true) }/*是否使用 -c copy 原音轨复制，速度快且无损，但时间精度有一个关键帧的误差*/

    var outtext by remember { mutableStateOf("${textdata}output.mp3")}

    // 用于控制下拉菜单是否展开的状态
    var expanded by remember { mutableStateOf(false) }

    var autoFormat by remember { mutableStateOf(true) }
    // 菜单项列表
    /**
     *     FLAC: .flac(Free Lossless Audio Codec): 是一种无损音频压缩格式，可以在不损失音质的情况下减小文件大小。
     *     M4A: .m4a 是MPEG-4音频文件的标准扩展名，通常用于存储AAC编码的音频，但也可以包含其他编码格式。
     *     MP3: .mp3(MPEG Layer III): 是最流行的有损音频压缩格式之一，通过牺牲一定的音质来大幅减小文件大小。
     *     RM: .rm(RealMedia): 是由RealNetworks开发的一种多媒体容器格式，常用于互联网上的音频和视频流。
     *     SPDIF: .spdif(Sony/Philips Digital Interface): 是一种数字音频传输接口，用于在设备之间传输未压缩的数字音频信号。
     *     WAV: .wav(Waveform Audio File Format): 是微软和IBM共同开发的一种无损音频格式，常用于Windows系统，支持多种音频编码。
     *     AIFF: .aiff 或 .aif(Audio Interchange File Format): 是一种无损音频格式，最初由苹果公司开发，常用于Macintosh平台，支持多种采样率和位深度。
     *     AU: .au 是一种常见的UNIX系统的音频文件格式，通常包含单声道或立体声的未压缩音频数据。
     *     CAF: .caf(Core Audio Format): 是苹果公司开发的一种容器格式，可以容纳几乎无限的音频数据，支持高分辨率音频和元数据。
     *     DTS .dts(Digital Theater Systems): 是一种多声道音频格式，用于电影院的数字音效，也用于家庭影院系统。
     * */
    val items = listOf("flac","mp3","wav","m4a","rm","aiff","aif","au","caf","dts","spdif")
    // 选中的菜单项
    var selectedIndex by remember { mutableStateOf(0) }
    //焦点管理
    val focusManager = LocalFocusManager.current
    var cutShow by remember { mutableStateOf(false)} //开启剪辑

//    val timeFormat= DateTimeFormatter.ofPattern("HH:mm:ss.SSS")
    var startTime:String by remember { mutableStateOf("00:00:00.000")}
    var endTime:String by remember { mutableStateOf("00:00:00.000")}

    var openSnackbar by remember { mutableStateOf(false) }//控制提示框


    /*Text(text = "mainPage")*/

    val dirLauncher= rememberLauncherForActivityResult(
        contract =  ActivityResultContracts.OpenDocumentTree() ,
        onResult = {
            runResult=""

            it?.let {
//                URIdata.value= it//FileUri.getPathByUri(it)?:""
                Log.i("!!!!!!!!!!!!!!!!!!", it.toString())
//                UriData.value=it
                appPath.input(it)
                textdata = appPath.input()
            }
        })
    val fileLauncher= rememberLauncherForActivityResult(
        contract =  ActivityResultContracts.GetContent(),
        onResult = {
            runResult=""

            it?.let {
//                URIdata.value= it//FileUri.getPathByUri(it)?:""
                Log.i("!!!!!!!!!!!!!!!!!!", it.toString())
//                UriData.value=it
                appPath.input(it)
                textdata = appPath.input()
            }
        })

//    Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center) {
        Column(modifier = Modifier
            .fillMaxSize()
            .padding(bottom = 50.dp)
            .pointerInput(Unit) {
                detectTapGestures {
                    // When the screen is tapped, request focus on the TextField
                    focusManager.clearFocus()
                    openSnackbar = false
//                    outtext =textdata.suffix(items[selectedIndex])
                }
            }, verticalArrangement =Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {

            Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center){
                Text(
                    text = if (pathType) "目录模式" else "文件模式",
                    fontSize = 18.sp /*color = MaterialTheme.colors.primary*/
                )
                Switch(modifier = Modifier.size(120.dp),
                    checked = pathType,
                    colors = SwitchDefaults.colors(
                        checkedThumbColor = MaterialTheme.colorScheme.primary,
                        checkedTrackColor = colorResource(id = R.color.musicOrange),
//                        checkedBorderColor = colorResource(id = R.color.musicOrange),

                    ),
                    onCheckedChange = {
                        pathType=it
                        if(pathType)cutShow=false
                })
            }
            Text("目标:", fontSize = 20.sp, modifier = Modifier
                .padding(10.dp)
//                .align(Alignment.Start)
                .width(330.dp))

            Text(
                /*enabled = false,
                readOnly = true,*/
                modifier = Modifier
                    .width(330.dp)
                    .border(
                        1.dp,
                        color = MaterialTheme.colorScheme.primary,
                        shape = RoundedCornerShape(5.dp)
                    )
                    .padding(16.dp)
                    .clickable {
                        Log.i("!!!!!!!!!", "Text had clicked!")
                        if (pathType)
                            dirLauncher.launch(null)//(intent)
                        else
                            fileLauncher.launch("*/*")
                    },
                text = textdata,
                style = TextStyle(
                    fontSize = 14.sp,
                    color = colorResource(id = R.color.black),
                    fontWeight = FontWeight.Bold
                ),
                onTextLayout={
                    outtext =textdata.suffix(items[selectedIndex])
                }
            )
            Spacer(modifier = Modifier.height(10.dp))

            OutlinedTextField(
                label = { Text("输出：", color = colorResource(R.color.black),
                                            style = TextStyle(fontWeight = FontWeight.Bold)
                ) },
                modifier = Modifier
                    .width(330.dp),
                colors = TextFieldDefaults.colors(
                    focusedTextColor = Color.Black,
                    focusedContainerColor = Color.White,
                    unfocusedContainerColor = Color.White,
                    disabledContainerColor = Color.White,
                    unfocusedIndicatorColor = MaterialTheme.colorScheme .primary
                ),

                value = outtext,
                textStyle = TextStyle(
                    fontSize = 13.sp,
                    fontWeight = FontWeight.Bold
                ),
                onValueChange = {
                    newText->
                    outtext = newText
                    Log.i("TextField()","input change value: ${newText}")
                },keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Done),
                keyboardActions = KeyboardActions(onDone = {
                    Log.i("input Done!!!","put msg:${startTime}")
                    focusManager.clearFocus()
                })
            )
            Row (
                Modifier
//                    .padding(5.dp)
                    .align(Alignment.End)
                    .offset(x = (-22).dp),  verticalAlignment = Alignment.CenterVertically){
                Checkbox( checked = autoFormat, colors = CheckboxDefaults.colors(
                    checkedColor = MaterialTheme.colorScheme .primary, // 选中时的颜色
                    uncheckedColor = MaterialTheme.colorScheme.primary, // 未选中时的颜色
                    checkmarkColor = MaterialTheme.colorScheme.onPrimary, // 勾

                ), onCheckedChange = {
                    autoFormat=it
                    if(autoFormat) {
                        outtext = textdata.suffix(items[selectedIndex])
                        fileType = items[selectedIndex]
                    }

                })
                Text(text = "自动转码", modifier = Modifier.offset(x= (-12).dp))
            // 下拉菜单的锚点，这里使用一个文本框
                if(autoFormat) Box(
                    Modifier
//                        .align(Alignment.End)
                        .padding(8.dp)

                        .border(
                            1.dp,
                            color = MaterialTheme.colorScheme.primary,
                            shape = RoundedCornerShape(5.dp)
                        )

                ) {
                    var menuWidth by remember { mutableStateOf(1)}
                    Text(
                        text = items[selectedIndex],
                        modifier = Modifier
                            .clickable(enabled = buttonState.clickable) { expanded = !expanded }
                            .align(Alignment.Center)
                            .padding(10.dp)

                            .onGloballyPositioned { coordinates ->
                                // 获取控件的宽度
                                menuWidth = coordinates.size.width
                            },

                    )
                    DropdownMenu(
                        expanded = expanded,
                        onDismissRequest = { expanded = false },
                        modifier = Modifier.width(menuWidth.dp)
                    ) {
                        items.forEachIndexed { index, s ->
                            DropdownMenuItem(
                                onClick = {
                                    selectedIndex = index
                                    expanded = false
                                    if(autoFormat) {
                                        outtext = textdata.suffix(items[selectedIndex])
                                        fileType = items[index]
                                    }
                                },
                                text = { Text(text = s) }
                            )
                        }
                    }
                }
            }
            Text(text = "简易剪辑"+ if(!cutShow) " ▼" else " ▲",
                Modifier
                    .align(Alignment.Start)
                    .offset(x = 35.dp, y = (-5).dp)
                    .clickable {
                        if (pathType) Agent.ToastLog("目录不支持剪辑")
                        else cutShow = !cutShow
                    },
                color = MaterialTheme.colorScheme.primary)

            if (cutShow)Column(modifier = Modifier
                .offset(y = (-5).dp)
                .border(
                    1.dp,
                    color = Color.Gray,
                    shape = RoundedCornerShape(5.dp)
                )
                .align(Alignment.CenterHorizontally)
                .width(340.dp)) {

                Row(
                    Modifier
                        .fillMaxWidth()
                        .offset(y = 15.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center){
                    Text(text = if(copyCut)"原音轨" else "重采样", fontSize = 14.sp, modifier = Modifier.offset(x=(-15).dp))
                    val scope = rememberCoroutineScope()
                    // 当Text被点击时显示弹窗

                    Text(text = " ?",
                        color = MaterialTheme.colorScheme.primary,
                        modifier = Modifier
                            .offset(x = (-15).dp)
                            .size(20.dp)
                            .border(
                                1.dp,
                                color = MaterialTheme.colorScheme.primary,
                                shape = RoundedCornerShape(10.dp)
                            )
                            .clickable(onClick = {
                                openSnackbar = true
                            })
                    )

                    Switch(modifier = Modifier
                        .width(50.dp)
                        .height(30.dp),
                        checked = copyCut,
                        colors = SwitchDefaults.colors(
                            checkedThumbColor = MaterialTheme.colorScheme.primary,
                            checkedTrackColor = colorResource(id = R.color.musicOrange),
                        ),
                        onCheckedChange = {
                            copyCut=it
                        })
                }
                if(openSnackbar)Snackbar(
                    modifier = Modifier.width(200.dp)/*.onFocusChanged {
                        if (!it.isFocused) {
                            openSnackbar=false
                        }
                    }*/,
                    content = { Text("原音轨：直接复制原音频的片段，速度快，无损，但时间精度有误差(一个关键帧)，大概几十毫秒,只在同格式剪辑有效。\n"
                            +"重采样：对音频重新解析读写一次，时间精度精确到毫秒，过程可能会丢失一些细节帧。") }
                )

                Row(
                    Modifier
                        .padding(20.dp)
                        .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.Center) {
                    OutlinedTextField(
                        label = { Text(text = "起点")},
                        modifier = Modifier
                            .width(133.dp)
                            .height(60.dp)
                            .onFocusChanged {
                                if (!it.isFocused) {
                                    Log.i("input Done!!!", "put msg:${startTime}")
                                    if (!startTime.isValidTime())
                                        startTime = startTime.formatTimeString()
                                }
                            },
                        colors = TextFieldDefaults.colors(
                            unfocusedIndicatorColor = MaterialTheme.colorScheme .primary
                        ),
                        value = startTime,
                        onValueChange = { newValue ->
                            startTime = newValue
                            Log.i("input()", "put msg:${newValue}")
                        },

                        keyboardOptions = KeyboardOptions(
                            keyboardType = KeyboardType.Number,
                            imeAction = ImeAction.Done
                        ),
                        keyboardActions = KeyboardActions(onDone = {
                            focusManager.clearFocus()
                        })
                    )
                    Spacer(Modifier.width(30.dp))
                    OutlinedTextField(
                        label = { Text(text = "终点")},
                        modifier = Modifier
                            .width(133.dp)
                            .height(60.dp)
                            .onFocusChanged {
                                if (!it.isFocused) {
                                    Log.i("input Done!!!", "put msg:${endTime}")
                                    if (!endTime.isValidTime())
                                        endTime = endTime.formatTimeString()
                                }
                            },
                        colors = TextFieldDefaults.colors(
                            unfocusedIndicatorColor = MaterialTheme.colorScheme .primary
                        ),
                        value = endTime,
                        onValueChange = { newValue ->
                            endTime = newValue
                            Log.i("input()", "put msg:${newValue}")
                        },

                        keyboardOptions = KeyboardOptions(
                            keyboardType = KeyboardType.Number,
                            imeAction = ImeAction.Done
                        ),
                        keyboardActions = KeyboardActions(onDone = {
                            focusManager.clearFocus()
                        })
                    )
                }
            }

//            Spacer(Modifier.height(60.dp))
            Column(Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {

                Button(
                    onClick = {
//                FileSelector(mainA!!)
//                val intent = appPath.fileSelect()
                        FFMPEG.get().clear()//清空上一次执行的配置项

                        if(cutShow && startTime != endTime)
                            FFMPEG.init(
                                timeS = startTime,
                                timeE = endTime,
                                sampling = copyCut)


                        if(!pathType){
                            if(File(textdata).isDirectory) {
                                Agent.ToastLog("当前为文件模式，请选择一个文件")
                                return@Button
                            }else if(textdata == outtext){
                                Agent.ToastLog("输入与输出文件名相同")
                                return@Button
                            }
                        }

                        Log.i("debug", "musicNameGetUri:$textdata")
                        if (perhandler.allFile.value) {
//                buttonRun(UriData.value.toString())
                            Agent.log("original path: $textdata")
                            val newname = rename(textdata)
                            if (newname != textdata) textdata = newname

                            modeSwitch(1,true)//开启解密
                            modeSwitch(2,autoFormat)
                            if(startTime != endTime)modeSwitch(3,cutShow)
                            buttonRun(textdata,outtext)
                        }
                    },
                    Modifier.size(100.dp),
                    shape = RoundedCornerShape(100),
                    enabled = buttonState.clickable
                ) {
                    Text(buttonState.text, fontSize = buttonState.size)
                }
                Spacer(Modifier.height(30.dp))
                Text(
                    text = runResult,
                    fontSize = 18.sp,
                    modifier = Modifier.offset(y = (-15).dp),
                    color =if (runResult.contains("失败")) {
                        musicRed
                    } else if (runResult.contains(other="成功")) {
                        musicGreen3 }
                    else {
                        black
                    }
                )
            }

        }
    }
//}

fun runState(value:Int){
    when(value){
        0-> buttonState = normal
        1-> buttonState = run
    }
}


@Preview(showBackground = true )
@Composable
private fun DefaultPreview() {
    MusicToolsTheme {
        MainPage()
    }
}

/**
 * 目前已经获取到文件content，查看如何使用它
 *https://blog.csdn.net/qq_37858386/article/details/123147090
 * https://blog.csdn.net/coloskk/article/details/124380366
 * 如何获取context
 *
 * contentPath不能成功转换出地址//新方法已解决
 *
 * 如何获取目录的路径
 *
 * 参考方法
 * https://blog.csdn.net/molihuan/article/details/125569956
 * https://www.orcode.com/question/1185149_k97f11.html
 *
 *使用了https://blog.csdn.net/weixin_44370506/article/details/111828374的文件选择器 //不好用，有点麻烦
 *
 * compose 文件选择器
 * https://blog.csdn.net/LiePy/article/details/125797893  //利用compose实现文件选择
 *
 *
 *
 * 完善输出显示框逻辑：
 * 1.增加输出格式选择
 * 2.增加时间输入
 * 3.增加是否无损剪辑（设置页面）
 *
 * 监听输入框的变化，对应修改
 * 匹配输出框的宽度，现在不对齐
 * 有一个bug ，解密失败不会执行ffmpeg（），是否要独立出来另外一个函数独立解决呢？
 *
 * 解密后不要恢复按钮，要等到转码完成，运行转码的前面时候加个 if else 就可以了 ok
 * 精简日志输出 ok
 * ffmpeg 执行入口 要独立出来吗？ 需要格式检测的配合
 * 如果不勾选自动转码，如何实现不会执行ffmpeg的转码模式呢？目前只能区分自动模式和单解密，单解密要精细到是否使用简易剪辑
 *
 * ---------------
 * 加个常用音频格式检测？ 需要，优先做这个，可以省去很多麻烦 ok
 * ffmpeg还有其他数据没有init进去，需要更新代码 ok
 *
 * 建立一个解密成功列表，ffmpeg()成功后要搜索此列表，如果在其中，需要删除该文件 ok
 *
 *----------------
 *
 *
 * */